#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>

#define ROW 15
#define COL 15
#define NUM 5

int piece[ROW][COL];
int step;
int old_r = -1;
int old_c = -1;

int computer;
int player;
int computer_value[ROW][COL];
int player_value[ROW][COL];

void show_board();
void show_piece(int, int, int);

int is_in(int r, int c);
int is_empty(int r, int c);
int is_win(int, int);

static int get_value(char s[4][16], int w);
static void set_one_value(int r, int c, int w);
static void set_all_value();
void analysis(int *r, int *c, int w);

int player_input(int *r, int *c, int w);
int computer_input(int *r, int *c, int w);

int main(int argc, char *argv[])
{
	int r, c, w;

	show_board();
	while (1)
	{
		if ((w = step % 2 + 1) == argc)
		{
			if (computer_input(&r, &c, w))
			{
				show_piece(r, c, w);
			}

			if (is_win(r, c))
				break;
		}
		else
		{
			if (player_input(&r, &c, w))
			{
				show_piece(r, c, w);
			}

			if (is_win(r, c))
				break;
		}
	}

	printf("game over\n");

	return 0;
}

int is_in(int r, int c)
{
	return r >= 0 && r < ROW && c >= 0 && c < COL;
}

int is_empty(int r, int c)
{
	return is_in(r, c) && piece[r][c] == 0;
}

void show_board()
{
	int i, j;

	system("clear");

	printf("  ");
	for (i = 0; i < ROW; ++i)
		printf(" %x ", i);
	printf("\n");

	for (i = 0; i < ROW; ++i)
	{

		printf("%x ", i);
		for (j = 0; j < COL; ++j)
		{
			if (piece[i][j] == 0)
				printf(" %c ", '*');
			else
			{
				if (piece[i][j] == 1)
					printf("\e[37;40m %d \e[0m", piece[i][j]);
				else
					printf("\e[30;47m %d \e[0m", piece[i][j]);

			}
		}
		printf("\n");
	}
	printf("\n");
}

void show_piece(int r, int c, int w)
{
	if (!is_in(r, c))
		return;

	old_r = r;
	old_c = c;

	piece[r][c] = w;
	step += 1;

	show_board();
}


int is_win(int current_row, int current_col)
{
	int i, j, r, c, w;
	int dx[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };
	int dy[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
	int dn[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };

	if (is_empty(current_row, current_col) || !is_in(current_row, current_col))
		return 0;

	w = piece[current_row][current_col];
	for (i = 0; i < 8; ++i)
	{
		r = current_row;
		c = current_col;
		for (j = 1; j < NUM; ++j)
		{
			r += dy[i];
			c += dx[i];
			if (is_in(r, c) && w == piece[r][c])
				++dn[i];
			else
				break;
		}
	}
	if (dn[0] + dn[7] > NUM || dn[1] + dn[6] > NUM || dn[2] + dn[5] > NUM || dn[3] + dn[4] > NUM)
		return 1;

	return 0;
}

int player_input(int *r, int *c, int w)
{
	printf("input row and col: ");
	scanf("%d %d", r, c);
	while (getchar() != '\n');


	return is_in(*r, *c) && is_empty(*r, *c);
}

int get_value(char s[4][16], int w)
{
	int i;
	int num[6][4] = { };

	for (i = 0; i < 4; ++i)
	{
		if (strlen(s[i]) < 5);
		else if (strstr(s[i], "000000010000000"))
			++num[1][0];
		else if (strstr(s[i], "0000001000000"))
			++num[1][1];
		else if (strstr(s[i], "11111"))
			++num[5][0];
		else if (strstr(s[i], "011110"))
			++num[4][0];
		else if (strstr(s[i], "1011101"))
			++num[4][0];
		else if (strstr(s[i], "11011011"))
			++num[4][0];
		else if (strstr(s[i], "111010111"))
			++num[4][0];
		else if (strstr(s[i], "11110"))
			++num[4][2];
		else if (strstr(s[i], "01111"))
			++num[4][2];
		else if (strstr(s[i], "11101"))
			++num[4][3];
		else if (strstr(s[i], "11011"))
			++num[4][3];
		else if (strstr(s[i], "10111"))
			++num[4][3];
		else if (strstr(s[i], "011100"))
			++num[3][0];
		else if (strstr(s[i], "001110"))
			++num[3][0];
		else if (strstr(s[i], "011010"))
			++num[3][1];
		else if (strstr(s[i], "010110"))
			++num[3][1];
		else if (strstr(s[i], "11100"))
			++num[3][2];
		else if (strstr(s[i], "01110"))
			++num[3][2];
		else if (strstr(s[i], "00111"))
			++num[3][2];
		else if (strstr(s[i], "11010"))
			++num[3][3];
		else if (strstr(s[i], "10110"))
			++num[3][3];
		else if (strstr(s[i], "11001"))
			++num[3][3];
		else if (strstr(s[i], "10101"))
			++num[3][3];
		else if (strstr(s[i], "01101"))
			++num[3][3];
		else if (strstr(s[i], "10011"))
			++num[3][3];
		else if (strstr(s[i], "01011"))
			++num[3][3];
		else if (strstr(s[i], "000110"))
			++num[2][0];
		else if (strstr(s[i], "001100"))
			++num[2][0];
		else if (strstr(s[i], "011000"))
			++num[2][0];
		else if (strstr(s[i], "11000"))
			++num[2][1];
		else if (strstr(s[i], "01100"))
			++num[2][1];
		else if (strstr(s[i], "00110"))
			++num[2][1];
		else if (strstr(s[i], "00011"))
			++num[2][1];
	}

	if (num[5][0] > 0)
		return (w == computer) ? 55000 : 50000;
	if (num[4][0] > 0)
		return (w == computer) ? 45000 : 40000;
	if (num[4][2] + num[4][3] > 1)
		return (w == computer) ? 45000 : 40000;
	if (num[4][2] + num[4][3] > 0 && num[3][0] + num[3][1] > 0)
		return (w == computer) ? 45000 : 40000;
	if (num[3][0] + num[3][1] > 1)
		return (w == computer) ? 35000 : 30000;

	if (w == computer)
	{
		return num[4][2] * 37000 + num[4][3] * 36000 + num[3][0] * 6000 + num[3][1] * 5000 + num[3][2] * 4000 + num[3][3] * 3000 + num[2][0] * 1000 + num[2][1] * 900 + num[1][0] * 200 + num[1][1] * 100;
	}
	else
	{
		return num[4][1] * 7 + num[3][0] * 6 + num[3][1] * 5 + num[2][0] * 4 + num[2][1] * 3 + num[1][0] * 2 + num[1][1] * 1;
	}

	return 0;
}

void set_one_value(int r, int c, int w)
{
	int i, j, rr, cc, rb, re, cb, ce;
	int dx[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };
	int dy[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
	int dn[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
	char ds[4][16];

	for (i = 0; i < 8; ++i)
	{
		rr = r;
		cc = c;
		for (j = 0;; ++j)
		{
			rr += dy[i];
			cc += dx[i];
			if (!is_in(rr, cc))
				break;
			if (piece[rr][cc] == w || piece[rr][cc] == 0)
				++dn[i];
			else
				break;
		}
	}

	for (i = 0; i < 4; ++i)
	{
		j = 0;
		rb = r + dy[i] * (dn[i] - 1);
		cb = c + dx[i] * (dn[i] - 1);
		re = r + dy[7 - i] * (dn[7 - i] - 1);
		ce = c + dx[7 - i] * (dn[7 - i] - 1);
		if (i < 3)
		{
			while (rb <= re)
			{
				if (rb == r || piece[rb][cb] == w)
					ds[i][j++] = '1';
				else
					ds[i][j++] = '0';
				rb += dy[7 - i];
				cb += dx[7 - i];
			}
		}
		else
		{
			while (cb <= ce)
			{
				if (cb == c || piece[rb][cb] == w)
					ds[i][j++] = '1';
				else
					ds[i][j++] = '0';
				rb += dy[7 - i];
				cb += dx[7 - i];
			}
		}
		ds[i][j] = '\0';
	}

	if (w == computer)
		computer_value[r][c] = get_value(ds, computer);
	else if (w == player)
		player_value[r][c] = get_value(ds, player);
}

void set_all_value()
{
	int r, c;

	for (r = 0; r < ROW; ++r)
		for (c = 0; c < COL; ++c)
		{
			computer_value[r][c] = -1;
			player_value[r][c] = -1;
		}

	for (r = 0; r < ROW; ++r)
		for (c = 0; c < COL; ++c)
			if (is_empty(r, c))
			{
				set_one_value(r, c, computer);
				set_one_value(r, c, player);
			}
}

void analysis(int *r, int *c, int w)
{
	int i, j, max;

	srand(time(0));

	computer = w;
	player = (computer == 1) ? 2 : 1;

	set_all_value();

	for (max = -1, i = 0; i < ROW; ++i)
	{
		for (j = 0; j < COL; ++j)
		{
			if (!is_empty(i, j))
				continue;

			if (max < computer_value[i][j] || (max == computer_value[i][j] && rand() % 2))
			{
				max = computer_value[i][j];
				*r = i;
				*c = j;
			}

			if (max < player_value[i][j])
			{
				max = player_value[i][j];
				*r = i;
				*c = j;
			}
		}
	}
}

int computer_input(int *r, int *c, int w)
{
	analysis(r, c, w);

	return is_empty(*r, *c);
}
